package com.whmall.service.crm.module.suppliercreditscore.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whmall.component.entity.dto.PageReqDTO;
import com.whmall.component.entity.dto.PageRspDTO;
import com.whmall.component.util.NumberUtils;
import com.whmall.service.crm.entity.dto.suppliercreditscore.*;
import com.whmall.service.crm.module.suppliercreditscore.SupplierCreditScoreSetting;
import com.whmall.service.crm.module.suppliercreditscore.dao.SupplierCreditScoreChangeHistoryMapper;
import com.whmall.service.crm.module.suppliercreditscore.dao.SupplierCreditScoreMapper;
import com.whmall.service.crm.module.suppliercreditscore.dao.SupplierCreditScoreProblemHistoryMapper;
import com.whmall.service.crm.module.suppliercreditscore.entity.SupplierCreditScoreChangeHistoryDO;
import com.whmall.service.crm.module.suppliercreditscore.entity.SupplierCreditScoreDO;
import com.whmall.service.crm.module.suppliercreditscore.entity.SupplierCreditScoreProblemHistoryDO;
import com.whmall.service.crm.module.suppliercreditscore.entity.qo.SupplierCreditScoreChangeHistoryQO;
import com.whmall.service.crm.module.suppliercreditscore.entity.qo.SupplierCreditScoreQO;
import com.whmall.service.crm.module.suppliercreditscore.enumeration.CreditScoreChangeTypeEnum;
import com.whmall.service.crm.module.suppliercreditscore.service.SupplierCreditScoreService;
import com.whmall.service.crm.module.suppliercreditscore.service.SupplierCreditScoreSettingService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Author：yangdong
 * Date：2020/12/12
 * Description：
 */
@Service
public class SupplierCreditScoreServiceImpl implements SupplierCreditScoreService {

    @Autowired
    private SupplierCreditScoreMapper scoreMapper;
    @Autowired
    private SupplierCreditScoreChangeHistoryMapper changeHistoryMapper;
    @Autowired
    private SupplierCreditScoreProblemHistoryMapper problemHistoryMapper;
    @Autowired
    private SupplierCreditScoreSettingService settingService;


    @Override
    public PageRspDTO<SupplierCreditScoreRspDTO> page(PageReqDTO pageReqDTO, SupplierCreditScoreQueryReqDTO queryReqDTO) {
        PageInfo<SupplierCreditScoreDO> pageInfo = PageHelper.startPage(pageReqDTO.getPageNum(), pageReqDTO.getPageSize()).doSelectPageInfo(() -> scoreMapper.list(SupplierCreditScoreQO.builder().id(queryReqDTO.getId()).build()));
        List<SupplierCreditScoreSetting> settingList = settingService.getAll();
        List<SupplierCreditScoreRspDTO> list = pageInfo.getList().stream().map(e -> {
                    SupplierCreditScoreRspDTO rspDTO = new SupplierCreditScoreRspDTO();
                    BeanUtils.copyProperties(e, rspDTO);
                    rspDTO.setCreditRankName(settingList.stream()
                            .filter(s -> s.getIsEnabled() && s.getMinScore() <= e.getScore() && e.getScore() <= s.getMaxScore())
                            .findFirst()
                            .map(SupplierCreditScoreSetting::getName)
                            .orElse(""));
                    return rspDTO;
                }).collect(Collectors.toList());
        return new PageRspDTO<>(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(), (int) pageInfo.getTotal(), list);
    }

    @Override
    public PageRspDTO<SupplierCreditScoreChangeHistoryRspDTO> changeHistoryPage(Long id, PageReqDTO pageReqDTO, SupplierCreditScoreChangeHistoryQueryReqDTO queryReqDTO) {
        SupplierCreditScoreChangeHistoryQO changeHistoryQO = new SupplierCreditScoreChangeHistoryQO();
        BeanUtils.copyProperties(queryReqDTO, changeHistoryQO);
        changeHistoryQO.setSupplierId(id);
        PageInfo<SupplierCreditScoreChangeHistoryDO> pageInfo = PageHelper.startPage(pageReqDTO.getPageNum(), pageReqDTO.getPageSize()).doSelectPageInfo(() -> changeHistoryMapper.list(changeHistoryQO));
        List<SupplierCreditScoreChangeHistoryRspDTO> list = pageInfo.getList().stream().map(e -> {
            SupplierCreditScoreChangeHistoryRspDTO rspDTO = new SupplierCreditScoreChangeHistoryRspDTO();
            BeanUtils.copyProperties(e, rspDTO);
            return rspDTO;
        }).collect(Collectors.toList());
        return new PageRspDTO<>(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(), (int) pageInfo.getTotal(), list);
    }

    @Override
    @Transactional
    public void scoreChange(Long id, SupplierCreditScoreChangeHistoryCreateReqDTO reqDTO) {
        SupplierCreditScoreDO supplierCreditScoreDO = scoreMapper.selectById(id);
        SupplierCreditScoreChangeHistoryDO changeHistoryDO = SupplierCreditScoreChangeHistoryDO.builder()
                .supplierId(supplierCreditScoreDO.getId())
                .changeType(reqDTO.getChangeType().getValue())
                .businessKey(reqDTO.getBusinessKey())
                .createTime(new Date())
                .build();
        SupplierCreditScoreDO updateScoreDO = SupplierCreditScoreDO.builder()
                .id(supplierCreditScoreDO.getId())
                .updateTime(new Date())
                .build();
        List<CreditScoreChangeTypeEnum> orderChangeTypeList = Arrays.asList(CreditScoreChangeTypeEnum.SYSTEM_DEFAULT_PRAISE,
                CreditScoreChangeTypeEnum.CUSTOMER_PRAISE,
                CreditScoreChangeTypeEnum.CUSTOMER_NEGATIVE_RATINGS,
                CreditScoreChangeTypeEnum.QUALITY_PROBLEM,
                CreditScoreChangeTypeEnum.PACKAGE_PROBLEM,
                CreditScoreChangeTypeEnum.LOGISTICS_PROBLEM);
        // 通过订单类型得分，不能超过1000分
        if (orderChangeTypeList.contains(reqDTO.getChangeType())) {
            Integer orderBalance = 1000 - supplierCreditScoreDO.getOrderScore();
            changeHistoryDO.setChangeScore(orderBalance <= reqDTO.getChangeScore() ? orderBalance : reqDTO.getChangeScore());
            updateScoreDO.setOrderScore(updateScoreDO.getOrderScore() + changeHistoryDO.getChangeScore());
        } else {
            changeHistoryDO.setChangeScore(reqDTO.getChangeScore());
        }
        updateScoreDO.setScore(updateScoreDO.getScore() + changeHistoryDO.getChangeScore());
        if (CreditScoreChangeTypeEnum.QUALITY_PROBLEM.equals(reqDTO.getChangeType())) {
            updateScoreDO.setQualityProblemCount1(updateScoreDO.getQualityProblemCount1() + 1);
        } else if (CreditScoreChangeTypeEnum.PACKAGE_PROBLEM.equals(reqDTO.getChangeType())) {
            updateScoreDO.setPackageProblemCount1(updateScoreDO.getPackageProblemCount1() + 1);
        } else if (CreditScoreChangeTypeEnum.LOGISTICS_PROBLEM.equals(reqDTO.getChangeType())) {
            updateScoreDO.setLogisticsProblemCount1(updateScoreDO.getLogisticsProblemCount1() + 1);
        }
        scoreMapper.updateByIdSelective(updateScoreDO);
        changeHistoryMapper.insertSelective(changeHistoryDO);
        // TODO 任意类型问题订单数量大于3，发送消息，锁定公司。
        if (updateScoreDO.getQualityProblemCount1() >= 3 || updateScoreDO.getPackageProblemCount1() >= 3 || updateScoreDO.getLogisticsProblemCount1() >= 3) {

        }
    }

    @Override
    @Transactional
    public void resetProblemCount(Long id) {
        SupplierCreditScoreDO scoreDO = scoreMapper.selectById(id);
        problemHistoryMapper.insertSelective(SupplierCreditScoreProblemHistoryDO.builder()
                .companyId(scoreDO.getId())
                .qualityProblemCount1(scoreDO.getQualityProblemCount1())
                .packageProblemCount1(scoreDO.getPackageProblemCount1())
                .logisticsProblemCount1(scoreDO.getLogisticsProblemCount1())
                .createTime(new Date())
                .build());
        scoreMapper.updateByIdSelective(SupplierCreditScoreDO.builder()
                .id(scoreDO.getId())
                .qualityProblemCount1(0)
                .packageProblemCount1(0)
                .logisticsProblemCount1(0)
                .updateTime(new Date())
                .build());
    }

    @Override
    public Map<Long, SupplierCreditScoreImportantFieldRspDTO> listByIds(List<Long> ids) {
        if(CollectionUtils.isEmpty(ids)){
            return new HashMap<>(1);
        }
        List<SupplierCreditScoreSetting> settingList = settingService.getAll();
        return scoreMapper.list(SupplierCreditScoreQO.builder()
                .ids(ids)
                .build())
                .stream()
                .map(e -> {
                    SupplierCreditScoreImportantFieldRspDTO rspDTO = new SupplierCreditScoreImportantFieldRspDTO();
                    BeanUtils.copyProperties(e, rspDTO);
                    Optional<SupplierCreditScoreSetting> settingOptional = settingList.stream()
                            .filter(s -> s.getIsEnabled() && s.getMinScore() <= e.getScore() && e.getScore() <= s.getMaxScore())
                            .findFirst();
                    rspDTO.setCreditRank(settingOptional.map(SupplierCreditScoreSetting::getName).orElse(""));
                    rspDTO.setQuota(NumberUtils.divide100(settingOptional.map(SupplierCreditScoreSetting::getQuota).orElse(0L)));
                    return rspDTO;
                }).collect(Collectors.toMap(SupplierCreditScoreImportantFieldRspDTO::getId, e -> e));
    }
}
